import java.io.IOException;
import java.net.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;

import net.barkerjr.gameserver.GameServer.Request;
import net.barkerjr.gameserver.GameServer.RequestTimeoutException;
import net.barkerjr.gameserver.valve.SourceServer;
import net.sourceforge.rconed.SourceRcon;
import net.sourceforge.rconed.exception.*;
public class Rcon extends SourceRcon {
	public int port;
	String ip;
	String password;
	public int myport;
	String myip;
	ArrayList<String> tr;
	ArrayList<String> sub;
	Info info;
	GatherBot bot;
	ResultSet rs;
	Statement sql;
	SourceServer server;
	boolean open;
	DatagramSocket log;
	Rcon (String ip, int port, String password,String myip,int myport) {
		open=false;
		this.ip = ip;
		this.port = port;
		this.password = password;
		this.myip = myip;
		this.myport = myport;
		try {
			connect();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		tr = new ArrayList<String>();
		sub = new ArrayList<String>();
		this.server = SourceServer.getInstance(new InetSocketAddress(ip,port));
		try {
			try {
				server.load(2000, Request.INFORMATION);

			} catch (RequestTimeoutException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} finally {
			server.close();
		}

	}

	public void send(String command) {
		try {
			send(this.ip ,this.port ,this.password, command);
		} catch (SocketTimeoutException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadRcon e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ResponseEmpty e) {

		}
	}
	void connect () throws SocketException, UnknownHostException {
		//if (log != null && !log.isClosed())
		//	log.disconnect();
		send("log on ; logaddress_add " + this.myip + ":" + this.myport);
		log = new DatagramSocket(this.myport); 
		log.connect(InetAddress.getByName(this.ip) , this.port);
		Thread getlog = new Thread () {
			public void run() {
				DatagramPacket read = new DatagramPacket(new byte[16384],16384);
				//while (log.isConnected()) {
				while (true) {
					read = new DatagramPacket(new byte[16384],16384);
					try {
						log.receive(read);
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try {
						data(new String(read.getData()).substring(30));
					} catch (SocketTimeoutException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (BadRcon e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (ResponseEmpty e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}; 
		getlog.start();

	}
	void openClasses() {
		open=false;
		send("exec open.cfg");
	}
	void closeClasses() {
		open=true;
		send("exec close.cfg");
	}
	void data (String str) throws SocketTimeoutException, BadRcon, ResponseEmpty {
		if (bot != null) {
			bot.StatementCheck();
			if (!str.equalsIgnoreCase(""))
				System.out.println(str);
			String [] score = str.split("" + (char)34);
			//System.out.println(score.length);
			if (score.length > 5) {
				if (score[2].equalsIgnoreCase(" current score ")) {
					if (score[1].equalsIgnoreCase("Red"))
						bot.redScore = Integer.parseInt(score[3]);
					if (score[1].equalsIgnoreCase("Blue"))
						bot.blueScore = Integer.parseInt(score[3]);
				}
				if (score[3].equalsIgnoreCase("pointcaptured") && (score[5].equalsIgnoreCase("1") || score[5].equalsIgnoreCase("3"))) {
					if (open)
						openClasses();
					else
						closeClasses();
				}
			}
			info = new Info(str);
			if (info.cmd != null) {
				if (bot.live && info.cmd.split(" ").length > 1) {
					if (info.cmd.split(" ")[0].equals("disconnected")) {
						try {
							server.load(2000, Request.INFORMATION);
							if (server.numberOfPlayers < 7)
								bot.endGather();
						} catch (RequestTimeoutException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				/**
			char [] b = info.cmd.toCharArray();
			String test = "";
			for (int i = 0;i<b.length;i++) {
				test += " " + (int)b[i];
			}
			bot.msg("cmd:" + test + " ,equals:" + info.cmd.equals("STEAM USERID validated"));
				 **/
				if (info.cmd.split("" + (char)10)[0].equalsIgnoreCase("STEAM USERID validated")) {
					try {
						ResultSet rs = bot.sql.executeQuery("select * from users where steamid='"+info.steam+"'");
						if (rs.next()) {
							rs = bot.sql.executeQuery("select * from bans where deleted=0 and id=" + rs.getInt("id") + " and bantime > " + new Date().getTime()/1000);
							if (rs.next())
								send("kickid " + info.id);
						}
					} catch (SQLException e) {
						e.printStackTrace();
					}
				}
				if (info.cmd.equalsIgnoreCase("say") || info.cmd.equalsIgnoreCase("say_team")) {
					if (info.data.equalsIgnoreCase("!tr") && !tr.contains(info.steam)) {
						tr.add(info.steam);
						if (tr.size() == 7) {
							tr.clear();
							send("mp_tournament_restart");
							bot.startTime = new Date().getTime();
						} else {
							send("say " + tr.size() + "/7 Players Requested Tournament Restart");
						}	
					}
					if (info.data.equalsIgnoreCase("!sub") && !sub.contains(info.steam) && !bot.sub) {
						sub.add(info.steam);
						if (sub.size() == 7) {
							sub.clear();
							send("say Searching for sub...");
							bot.getSub();
						} else {
							send("say " + sub.size() + "/7 Players Requested Sub");
						}	
					}
				}
				if (info.cmd.equalsIgnoreCase("killed") && bot.live) {
					Info info2 = new Info((char)34 + info.data.split("\\(")[0]);
					if (info2.cmd != null) {
						try {
							sql = bot.sql;
							rs = sql.executeQuery("SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'weapon_statistics' AND COLUMN_NAME = '"+info2.data+"'");
							if (!rs.next())
								sql.execute("ALTER TABLE weapon_statistics add column "+info2.data+" int(1) NOT NULL DEFAULT 0");
							rs = sql.executeQuery("select * from weapon_statistics where steamid='" + info.steam + "'");
							if (!rs.next()) {
								sql.execute("insert into weapon_statistics (steamid) values ('" + info.steam + "')");
							}
							rs = sql.executeQuery("select * from weapon_statistics where steamid='" + info.steam + "'");
							if (rs.next()) {
								try {
									int kills = rs.getInt(info2.data) + 1;
									sql.execute("update weapon_statistics set "+info2.data+"="+kills+" where steamid='" + info.steam + "'");
								} catch (NullPointerException e) {
									System.out.println("Error:");
									System.out.println("info: " + info);
									System.out.println("info2: " + info2);
									e.printStackTrace();
								}

							}
						} catch (SQLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
			}
			String [] da = str.split("" + (char)34);
			if (da.length > 1 && da[0].length() > 1) {
				if (da[0].substring(0, da[0].length() - 1).equalsIgnoreCase("World triggered")) {
					if (da[1].equalsIgnoreCase("Round_Start") && !bot.reg) {
						if (!bot.live) {
							bot.live = true;
							bot.startTime = new Date().getTime();
							send("tv_record " + (bot.getID() - 1));
						}
						closeClasses();
					}
					if (da[1].equalsIgnoreCase("Game_Over") && bot.live) {
						bot.endGather();
					}
				}
			}
		}
	}
	public void setBot(GatherBot bot) {
		this.bot = bot;
		sql = bot.sql;
	}
}

